
	;;
	;; Entrance code for freeGSD. This does not much except
	;; allow grup to call the OS and define a few useful routines.
	;;

section .data

msg	equ	"cr0 register flags:\n  "
	
section .text

MULTIBOOT_PAGE_ALIGN   equ 1<<0
MULTIBOOT_MEMORY_INFO  equ 1<<1

MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
CHECKSUM               equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

; The Multiboot header (in NASM syntax)
align 4
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd CHECKSUM

extern	main
extern	itobs
extern	k_print
extern	__idt_handler

global	__common_idt_handler
global __flush_idt
global	start
global	__use_pages


start:
	;; 
	;; Well, now we are here (Duh).
	;; Status of things at this point: no paging, no interupts, but we DO have a GDT
	;; First, start the stack at 0x00210000 (65KBytes of stack space).
	;; Next thing to do is push the address of the boot info passed by
	;; GRUB and then call the kernel.c starting address.
	;;
	mov	esp,	0x00210000
	
	push	ebx
	call	main
	
	;; If we get to here (ideally, we shouln't) hang.
	jmp	hang

hang:
	jmp	hang

	

__use_pages:
	push	ebp
	mov	ebp, esp
	push	ebx
		
	;; Load cr3 with the address of the page dir.
	mov	eax,	[ebp + 8]
	shr	eax,	12
	shl	eax,	20
	mov	ebx,	cr3
	shl	ebx,	20
	shr	ebx,	20
	or	eax,	ebx
	mov	cr3,	eax

	;; Init paging mode
	cli
	
	mov	eax,	cr0
	xor	ebx,	ebx
	mov	ebx,	1
	shl	ebx,	31
	or	eax,	ebx

	mov	cr0,	eax	
	jmp	__paged_mode
	;; We are now in paging mode.

__paged_mode:
	sti
	pop	ebx
	pop	ebp
	ret


__idt_entrance:
	;; 
	;; Push the registers onto the stack.
	;; 
	push	word	ss
	push	word	gs
	push	word	fs
	push	word	es
	push	word	ds
	push	word	cs
	pushf
	pusha

	;;
	;; Call the C interupt handler
	;;
	 
	;; call	__idt_handler

	;;
	;; Return the registers back to their original state.
	;; 
	popa
	popf
	pop	word	cs
	pop	word	ds
	pop	word	es
	pop	word	fs
	pop	word	gs
	pop	word	ss

	;; Return
	ret

	;;
	;; __flush_idt(short limit, int addr)
	;; 
__flush_idt:
	push	ebp
	mov	ebp,	esp
	
	lidt	[ebp + 8]
	
	pop	ebp
	ret

	;; This code will configure our new segment
	;; registers. To get to the cs, we need to
	;; do a far jump, or a jump that includes a
	;; segment as well as an offset. In gdt.c we
	;; have decalred this as 'extern void gdt_flush()'
global gdt_flush		; So that our c code can link
extern gp			; gp

gdt_flush:
	lgdt [gp]		; Load the GDT with our special pointer
	mov ax, 0x10 		; 0x10 is the offset in the GDT to our data segment
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	jmp 0x08:flush2	 	; 0x08 is the offset to our code segment. This is the far jump
flush2:	
	ret 			; Returns to the C code

